import numpy as np
from numpy import*
with open(r"C:\Users\ASUS~\Desktop\新建文本文档.txt") as file:
    str_list = file.read()
    new_list = str_list.split("\n")
    '''
    ['1 2 11', '2 3 22', '3 1 33', '4 6 44', '5 3 55', '6 12 66', '7 6 77', '8 6 88', '9 3 99', '10 3 8']
    '''

for i in range(len(new_list)):
    new_list[i] = new_list[i].split()  #将列表中的每一个大元素，再以‘ ’劈分开,组成一个个小列表 ['1','2','11']
    '''
    [['1', '2', '11'], ['2', '3', '22'], ['3', '1', '33'], ['4', '6', '44'], ['5', '3', '55'], ['6', '12', '66'], ['7', '6', '77'], ['8', '6', '88'], ['9', '3', '99'], ['10', '3', '8']]
    '''

arry1 = np.array(new_list)         #将列表转换成二维数组
arry2 = arry1.astype(int)          #将数组中的数据类型转换成字符串
'''
[[ 1  2 11]
 [ 2  3 22]
 [ 3  1 33]
 [ 4  6 44]
 [ 5  3 55]
 [ 6 12 66]
 [ 7  6 77]
 [ 8  6 88]
 [ 9  3 99]
 [10  3  8]]
'''
# 将numpy数组转化为列表，并且对在第一行添加序列号
list_c=arry2.tolist() #[[1, 2, 11], [2, 3, 22], [3, 6, 33], [4, 6, 44], [5, 3, 55], [6, 12, 66], [7, 6, 77], [8, 6, 88], [9, 3, 99], [10, 3, 8]]
for i in range(len(list_c)):
    list_c[i].insert(0,i+1)     #在列表的每一行的第一个位置插入业务序号

# 根据列表的第三个字段周期从小到大进行排序
list_c.sort(key = lambda x: x[2],reverse=False)
print('按周期排序后：',list_c)
'''排序后的list_c: 
[[1, 1, 2, 11], [2, 2, 3, 22], [5, 5, 3, 55], [9, 9, 3, 99], [10, 10, 3, 8], [3, 3, 6, 33], [4, 4, 6, 44], [7, 7, 6, 77], [8, 8, 6, 88], [6, 6, 12, 66]]
'''

#计算周期的最大公约数 gcd(a,b,c) = gcd(gcd(a,b),c)
def GCDamong(a,b):
    big = max(a,b)
    small = min(a,b)
    if big%small==0:
        return small
    return GCDamong(big%small,small)

def LCMamong(a,b):
    if a * b == 0:
        return 0
    return a * b/(GCDamong(a,b))

def GCD_All(lst):   #参数为一个二维列表，可自行调节
    gcd = GCDamong(lst[0][2], lst[1][2])
    for i in range(2,len(lst)):
        gcd = GCDamong(gcd, lst[i][2])
    return gcd
# 计算周期的最小公倍数  lcm(a,b,c) = lcm(lcm(a,b),c)
def LCM_All(lst):
    lcm= LCMamong(lst[0][2], lst[1][2])
    for i in range(2, len(lst)):
        lcm = LCMamong(lcm, lst[i][2])
    return lcm

GCD = GCD_All(list_c)  #求业务1-10周期的最大公约数为1
LCM = LCM_All(list_c )
print('GCD:',GCD,' LCM: ',LCM)


u=1                                 #初始值为1，用来表示将业务序号和周期分成的不同组数，即行
n=len(list_c )
list_must=[]         # list_must存放每个基本周期都要调度的业务序号,也就是周期等于基本周期的业务
list_others=[[0]]    # list_others中存放的其他非基本周期发送的业务序号
list_time=[[0]]      # list_time存放list_others中业务的周期
list_number=[1]           # list_number存放的是分配好后的每组的业务个数
for k in range(0,n):   #用k来遍历每一个业务的周期和已分好组的进行比较，从第二个业务序号开始遍历
    if list_c[k][2] != GCD:
        list_time[0][0] = list_c[k][2]  # 找到第一个非基本周期的业务，将序号和周期分别插入
        list_others[0][0] = list_c[k][0]
        count = k  # 用来记录已经遍历多少个业务了，后续直接从count+1往下遍历
        break  # 周期是按从小到大的顺序排的，如果前面都不存在周期为基本周期的业务后面更不会存在，
    else:
        list_must.append(list_c[k][0])
# 开始接着从下标count+1往后遍历
for k in range(count + 1, n):
    flag=0                       #用来标志是否需要添加新组别
    for i in range(0,u):
        t=0
        for j in range(0,list_number[i]): #j用来遍历fenpei列表和list_x列表中每个组别下的具体元素
            r = GCDamong( list_time[i][j],list_c[k][2])
            t = t + 1/r
        if t<=1:
            list_time[i].append(list_c[k][2])
            list_others[i].append(list_c[k][0])
            list_number[i]+=1
            flag=1
            break   #用来跳出i的循环
        else:
            continue #继续取下一个i值,可能这个组放不下了，但后一个组可能能放进去
    if(flag==0):
        # 前面的组别已经按要求存满，需要开辟一个新的组存放当前周期和序号
        list_number.append(1)  #新组中最开始有一个元素。u插入的是1
        list_time.append([list_c[k][2]])
        list_others.append([list_c[k][0]])
        u=u+1

# 下面代码实现了把周期等于基本周期的先放入对应位置打包的每一个组别当中
list_dpc=[[] for i in range(int(LCM/GCD))] #用来存放最终发送业务先后顺序的组合
for j in range(0,int(LCM/GCD)): #  矩阵周期(最小公倍数)/基本周期(最大公约数)=形成的分配组数   即 LCM/GCD  详见论文
    for k in range(0,len(list_must)):
        list_dpc[j].append(list_must[k])
#print(list_dpc) [[3], [3], [3], [3], [3], [3], [3], [3], [3], [3], [3], [3]]

# 现在需要将list_others中的也放进去这个list_dpc中去
for i in range(0,len(list_others)):
    for j in range(0,len(list_others[i])):
        list_dpc[j].append(list_others[i][j])
#[[3, 1, 5, 6], [3, 2, 9], [3, 4, 10], [3, 7, 8], [3], [3], [3], [3], [3], [3], [3], [3]]
print('周期发送业务序号组合:  ', list_must)
print('生成的非周期业务序号组合:  ', list_others)
print('最终生成的发送集合：',list_dpc)





# print('-'*100)
# def txt_read(filename):
#     txt_dict = {}
#     with open(filename,'r+',encoding='UTF_8') as file:
#         data=file.readlines()# ['1 2 11\n', '2 3 22\n', '3 1 33\n', '4 6 44\n', '5 3 55\n', '6 12 66\n', '7 6 77', '8 6 88', '9 3 99', '10 3 8']
#         for line in data:    # 遍历每行的内容将取出来的字符串的最后面\n去掉
#             line = str(line).strip('\n') # '1 2 11'
#             #将字符串以' '进行劈分
#             line=line.split(" ") # 每个line是大列表中的一个小列表[1,2,11]
#             #索引为0的就是key，索引为1的就是value,构造一个字典
#             txt_dict[line[0]] = [int(line[1]),int(line[2])]
#     return txt_dict
#
# txt_dict = txt_read(r'C:\Users\ASUS~\Desktop\新建文本文档.txt')
# print(txt_dict)
#
# print(len(txt_dict))





















